D:\a\tools.proto\tools.proto\dynamic\src\buffer\view.rs
Line | Count | Source |
1 | | // Copyright (c) 2025, BlockProject 3D |
2 | | // |
3 | | // All rights reserved. |
4 | | // |
5 | | // Redistribution and use in source and binary forms, with or without modification, |
6 | | // are permitted provided that the following conditions are met: |
7 | | // |
8 | | // * Redistributions of source code must retain the above copyright notice, |
9 | | // this list of conditions and the following disclaimer. |
10 | | // * Redistributions in binary form must reproduce the above copyright notice, |
11 | | // this list of conditions and the following disclaimer in the documentation |
12 | | // and/or other materials provided with the distribution. |
13 | | // * Neither the name of BlockProject 3D nor the names of its contributors |
14 | | // may be used to endorse or promote products derived from this software |
15 | | // without specific prior written permission. |
16 | | // |
17 | | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
18 | | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
19 | | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
20 | | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
21 | | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
22 | | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
23 | | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
24 | | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
25 | | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
26 | | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
27 | | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | | |
29 | | use std::cell::{Cell, UnsafeCell}; |
30 | | use std::fmt::{Debug, Display}; |
31 | | use std::io::Write; |
32 | | use std::ops::{Index, IndexMut}; |
33 | | use std::rc::Rc; |
34 | | use crate::buffer::buffer::Buffer; |
35 | | use crate::component::{Component, util::DiscoverTool}; |
36 | | use crate::field::primitive::{PrimitiveType, PrimitiveValue, PrimitiveValueMut}; |
37 | | use bp3d_debug::trace; |
38 | | use crate::buffer::unsafe_buffer::UnsafeBuffer; |
39 | | |
40 | | #[derive(Debug)] |
41 | | pub struct Location { |
42 | | pub fixed: bool, |
43 | | pub offset: isize, |
44 | | pub size: usize, |
45 | | } |
46 | | |
47 | | #[derive(Debug)] |
48 | | pub(super) struct PathComponent { |
49 | | pub(super) name: String, |
50 | | pub(super) index: Cell<isize>, |
51 | | // Unfortunately RefCell is unusable because if RefCell then loops are forbidden. |
52 | | //TODO: Try to find better than UnsafeCell. |
53 | | pub(super) parent: UnsafeCell<Option<Rc<PathComponent>>> |
54 | | } |
55 | | |
56 | | pub struct BufferView<'a> { |
57 | | pub(super) path_component: Rc<PathComponent>, |
58 | | pub(super) buffer: Buffer<'a>, |
59 | | pub(super) children: Vec<BufferView<'a>>, |
60 | | pub(super) location: Location, |
61 | | pub(super) component: Option<Box<dyn Component>>, |
62 | | pub(super) items: Option<Vec<BufferView<'a>>>, |
63 | | pub(super) primitive: Option<Box<dyn PrimitiveType>>, |
64 | | } |
65 | | |
66 | | impl Debug for BufferView<'_> { |
67 | 5 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
68 | 5 | if self.primitive.is_none() { Branch (68:12): [True: 5, False: 0]
Branch (68:12): [True: 0, False: 0]
|
69 | 5 | write!(f, "BufferView {{ name: {}, location: {:?}, children: {:?} }}", self.path_component.name, self.location, self.children) |
70 | | } else { |
71 | 0 | write!(f, "BufferView {{ name: {}, location: {:?}, children: {:?}, primitive }}", self.path_component.name, self.location, self.children) |
72 | | } |
73 | 5 | } |
74 | | } |
75 | | |
76 | | impl Display for BufferView<'_> { |
77 | 12 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
78 | 12 | let path_max_width = self.get_path_max_width(); |
79 | 12 | let hex_max_width = self.get_hex_max_width(); |
80 | 12 | writeln!(f, "|-{:-^path_max_width$}-|-{:-^6}-|-{:-^6}-|-{:-^hex_max_width$}-|-{:-^10}-|", "", "", "", "", "")?0 ; |
81 | 12 | writeln!(f, "| {: ^path_max_width$} | {: ^6} | {: ^6} | {: ^hex_max_width$} | {: ^10} |", "Path", "Offset", "Size", "Hex", "Value")?0 ; |
82 | 12 | writeln!(f, "|-{:-^path_max_width$}-|-{:-^6}-|-{:-^6}-|-{:-^hex_max_width$}-|-{:-^10}-|", "", "", "", "", "")?0 ; |
83 | 12 | self.dump_children(f, path_max_width, hex_max_width)?0 ; |
84 | 12 | Ok(()) |
85 | 12 | } |
86 | | } |
87 | | |
88 | | impl<'a> BufferView<'a> { |
89 | 60 | fn get_path_max_width(&self) -> usize { |
90 | 60 | let mut path_max_width = 0; |
91 | 108 | for child48 in &self.children { |
92 | 48 | let len = child.get_path().len(); |
93 | 48 | if len > path_max_width { Branch (93:16): [True: 2, False: 1]
Branch (93:16): [True: 17, False: 28]
|
94 | 19 | path_max_width = len; |
95 | 29 | } |
96 | 48 | let other_len = child.get_path_max_width(); |
97 | 48 | if other_len > path_max_width { Branch (97:16): [True: 1, False: 2]
Branch (97:16): [True: 6, False: 39]
|
98 | 7 | path_max_width = other_len; |
99 | 41 | } |
100 | | } |
101 | 60 | path_max_width |
102 | 60 | } |
103 | | |
104 | 23 | fn get_hex_max_width(&self) -> usize { |
105 | 23 | if self.buffer.flat.get() { //If the buffer is flat then hex max width is by definition the Branch (105:12): [True: 1, False: 0]
Branch (105:12): [True: 8, False: 14]
|
106 | | // master buffer len. |
107 | 9 | return self.buffer.len() * 3; |
108 | 14 | } |
109 | 14 | let mut hex_max_width = 0; |
110 | 25 | for child11 in &self.children { |
111 | 11 | trace!({len=child.buffer.len()} {offset=child.buffer.offset}, "get_hex_max_width"); |
112 | 11 | let len = if child.buffer.len() == 0 { Branch (112:26): [True: 0, False: 0]
Branch (112:26): [True: 3, False: 8]
|
113 | 3 | 3 |
114 | | } else { |
115 | 8 | (child.buffer.len() + child.buffer.offset) * 3 |
116 | | }; |
117 | 11 | if len > hex_max_width { Branch (117:16): [True: 0, False: 0]
Branch (117:16): [True: 5, False: 6]
|
118 | 5 | hex_max_width = len; |
119 | 6 | } |
120 | 11 | let other_len = child.get_hex_max_width(); |
121 | 11 | if other_len > hex_max_width { Branch (121:16): [True: 0, False: 0]
Branch (121:16): [True: 0, False: 11]
|
122 | 0 | hex_max_width = other_len; |
123 | 11 | } |
124 | | } |
125 | 14 | hex_max_width |
126 | 23 | } |
127 | | |
128 | 60 | fn dump_children(&self, f: &mut std::fmt::Formatter<'_>, path_max_width: usize, hex_max_width: usize) -> std::fmt::Result { |
129 | 108 | for child48 in &self.children { |
130 | 48 | let value = child.get_primitive().map(|v| v.get()22 .to_string22 ()).unwrap_or("####".into()); |
131 | 48 | let bytes = format!("{:02X?}", child.buffer.as_bytes()).replace(",", ""); |
132 | 48 | let bytes = &bytes[1..bytes.len() - 1]; |
133 | 48 | let mut padding = String::from(""); |
134 | 382 | for _ in 0..child.buffer.offset48 { |
135 | 382 | padding += ".. "; |
136 | 382 | } |
137 | 48 | writeln!(f, "| {: <path_max_width$} | {: ^6} | {: ^6} | {: <hex_max_width$} | {: ^10} |", child.get_path(), child.buffer.offset, child.buffer.len(), padding + bytes, value)?0 ; |
138 | 48 | child.dump_children(f, path_max_width, hex_max_width)?0 ; |
139 | | } |
140 | 60 | Ok(()) |
141 | 60 | } |
142 | | |
143 | 58 | pub fn get_primitive(&self) -> Option<PrimitiveValue> { |
144 | 58 | self.primitive.as_ref().map(|v| PrimitiveValue::new32 (self.buffer.as_bytes()32 , &**v32 )) |
145 | 58 | } |
146 | | |
147 | 11 | pub fn get_primitive_mut(&mut self) -> Option<PrimitiveValueMut> { |
148 | 11 | self.primitive.as_ref().map(|v| PrimitiveValueMut::new(self.buffer.as_bytes_mut(), &**v)) |
149 | 11 | } |
150 | | |
151 | 16 | pub fn location_mut(&mut self) -> &mut Location { |
152 | 16 | &mut self.location |
153 | 16 | } |
154 | | |
155 | 0 | pub fn location(&self) -> &Location { |
156 | 0 | &self.location |
157 | 0 | } |
158 | | |
159 | 84 | pub fn buffer(&self) -> &Buffer<'a> { |
160 | 84 | &self.buffer |
161 | 84 | } |
162 | | |
163 | 18 | pub fn buffer_mut(&mut self) -> &mut Buffer<'a> { |
164 | 18 | &mut self.buffer |
165 | 18 | } |
166 | | |
167 | 18 | pub fn get(&self, path: &str) -> Option<&BufferView<'a>> { |
168 | 18 | let split = path.split("."); |
169 | 18 | let mut view = self; |
170 | 47 | for name30 in split { |
171 | 30 | let id = name.find('['); |
172 | 30 | let name = id.map(|v| &name[..v]1 ).unwrap_or(name); |
173 | 50 | view = view.children.iter()30 .find30 (|child| child.path_component.name == name)?0 ; |
174 | 30 | if let Some(id1 ) = id { Branch (174:20): [True: 1, False: 15]
Branch (174:20): [True: 0, False: 14]
|
175 | 1 | view = view.items.as_ref()?.get0 (id0 )?0 ; |
176 | 29 | } |
177 | | } |
178 | 17 | Some(view) |
179 | 18 | } |
180 | | |
181 | 0 | pub fn add_item(&mut self, mut view: BufferView<'a>) { |
182 | 0 | let mut items = self.items.take().unwrap_or_default(); |
183 | 0 | view.buffer.flat = self.buffer.flat.clone(); |
184 | 0 | for child in view.iter_mut() { |
185 | 0 | child.buffer.flat = self.buffer.flat.clone(); |
186 | 0 | } |
187 | 0 | *unsafe { &mut *view.path_component.parent.get() } = Some(self.path_component.clone()); |
188 | 0 | view.path_component.index.set((items.len() - 1) as _); |
189 | 0 | items.push(view); |
190 | 0 | self.items = Some(items); |
191 | 0 | self.buffer.flat.set(false); |
192 | 0 | } |
193 | | |
194 | 0 | pub fn remove_item(&mut self, index: usize) { |
195 | 0 | if let Some(items) = &mut self.items { Branch (195:16): [Folded - Ignored]
Branch (195:16): [True: 0, False: 0]
|
196 | 0 | items.remove(index); |
197 | 0 | for (i, v) in items.iter_mut().enumerate() { |
198 | 0 | v.path_component.index.set(i as _); |
199 | 0 | } |
200 | 0 | self.buffer.flat.set(false); |
201 | 0 | } |
202 | 0 | } |
203 | | |
204 | 1 | pub fn add_child(&mut self, mut view: BufferView<'a>) { |
205 | 1 | view.buffer.flat = self.buffer.flat.clone(); |
206 | 3 | for child in view1 .iter_mut1 () { |
207 | 3 | child.buffer.flat = self.buffer.flat.clone(); |
208 | 3 | } |
209 | 1 | *unsafe { &mut *view.path_component.parent.get() } = Some(self.path_component.clone()); |
210 | 1 | self.children.push(view); |
211 | 1 | self.buffer.flat.set(false); |
212 | 1 | } |
213 | | |
214 | 0 | pub fn clear(&mut self) { |
215 | 0 | self.children.clear(); |
216 | 0 | self.buffer.flat.set(false); |
217 | 0 | } |
218 | | |
219 | 16 | pub fn get_mut(&mut self, path: &str) -> Option<&mut BufferView<'a>> { |
220 | 16 | let split = path.split("."); |
221 | 16 | let mut view = self; |
222 | 38 | for name22 in split { |
223 | 22 | let id = name.find('['); |
224 | 22 | let name = id.map(|v| &name[..v]0 ).unwrap_or(name); |
225 | 42 | view = view.children.iter_mut()22 .find22 (|child| child.path_component.name == name)?0 ; |
226 | 22 | if let Some(id0 ) = id { Branch (226:20): [True: 0, False: 4]
Branch (226:20): [True: 0, False: 18]
|
227 | 0 | view = view.items.as_mut()?.get_mut(id)?; |
228 | 22 | } |
229 | | } |
230 | 16 | Some(view) |
231 | 16 | } |
232 | | |
233 | 6 | pub fn is_empty(&self) -> bool { |
234 | 6 | self.children.is_empty() |
235 | 6 | } |
236 | | |
237 | 0 | pub fn len(&self) -> usize { |
238 | 0 | self.children.len() |
239 | 0 | } |
240 | | |
241 | 0 | pub fn iter(&self) -> impl Iterator<Item=&BufferView<'a>> { |
242 | 0 | self.children.iter() |
243 | 0 | } |
244 | | |
245 | 3 | pub fn iter_mut(&mut self) -> impl Iterator<Item=&mut BufferView<'a>> { |
246 | 3 | self.children.iter_mut() |
247 | 3 | } |
248 | | |
249 | 1 | pub fn read_copy(&mut self, bytes: &[u8]) -> bp3d_proto::message::Result<usize> { |
250 | 1 | self.buffer.copy_from(bytes); |
251 | 1 | self.read() |
252 | 1 | } |
253 | | |
254 | 1 | pub fn read_view(&mut self, bytes: &'a [u8]) -> bp3d_proto::message::Result<usize> { |
255 | 1 | self.buffer.set_bytes(bytes); |
256 | 1 | self.read() |
257 | 1 | } |
258 | | |
259 | 41 | fn read(&mut self) -> bp3d_proto::message::Result<usize> { |
260 | 41 | trace!({name=&*self.path_component.name}, "attempt read"); |
261 | 41 | if self.location.fixed { Branch (261:12): [True: 3, False: 1]
Branch (261:12): [True: 13, False: 24]
|
262 | 16 | if self.buffer.len() < self.location.size { Branch (262:16): [True: 0, False: 3]
Branch (262:16): [True: 0, False: 13]
|
263 | 0 | return Err(bp3d_proto::message::Error::Truncated) |
264 | 16 | } |
265 | 16 | if !self.buffer.flat.get() { Branch (265:16): [True: 3, False: 0]
Branch (265:16): [True: 13, False: 0]
|
266 | 16 | self.buffer.unsafe_buffer = self.buffer.unsafe_buffer.index(..self.location.size); |
267 | 28 | for child12 in &mut self.children { |
268 | 12 | child.buffer.unsafe_buffer = self.buffer.unsafe_buffer.index(child.location.offset as usize..child.location.offset as usize + child.location.size); |
269 | 12 | child.buffer.offset = self.buffer.offset + child.location.offset as usize; |
270 | 12 | child.read()?0 ; |
271 | | } |
272 | 0 | } |
273 | 16 | return Ok(self.location.size); |
274 | 25 | } |
275 | 25 | if let Some(component12 ) = self.component.take() { Branch (275:16): [True: 0, False: 1]
Branch (275:16): [True: 12, False: 12]
|
276 | 12 | let mut tool = DiscoverTool::new(self.items.take(), std::mem::replace(&mut self.children, Vec::new())); |
277 | 12 | if let Err(e0 ) = component.read(self, &mut tool) { Branch (277:20): [True: 0, False: 0]
Branch (277:20): [True: 0, False: 12]
|
278 | 0 | self.component = Some(component); |
279 | 0 | return Err(e); |
280 | 12 | }; |
281 | 12 | self.component = Some(component); |
282 | 12 | let (mut items, children) = tool.into_inner(); |
283 | 12 | if let Some(items0 ) = &mut items { Branch (283:20): [True: 0, False: 0]
Branch (283:20): [True: 0, False: 12]
|
284 | 0 | let mut item_offset = 0; |
285 | 0 | for (index, item) in items.iter_mut().enumerate() { |
286 | 0 | item.path_component.index.set(index as _); |
287 | 0 | if item.location.offset != -1 { Branch (287:24): [True: 0, False: 0]
Branch (287:24): [True: 0, False: 0]
|
288 | 0 | item_offset = item.location.offset; |
289 | 0 | } |
290 | 0 | if item_offset as usize >= self.buffer.len() { Branch (290:24): [True: 0, False: 0]
Branch (290:24): [True: 0, False: 0]
|
291 | 0 | return Err(bp3d_proto::message::Error::Truncated); |
292 | 0 | } |
293 | 0 | unsafe { item.buffer.unsafe_buffer.delete() }; |
294 | 0 | item.buffer.unsafe_buffer = self.buffer.unsafe_buffer.index((item_offset as usize)..); |
295 | | // Again type inference is broken. |
296 | 0 | item.buffer.offset = self.buffer.offset + item_offset as usize; |
297 | 0 | let size = item.read()?; |
298 | 0 | if (item_offset as usize) + size > self.buffer.len() { Branch (298:24): [True: 0, False: 0]
Branch (298:24): [True: 0, False: 0]
|
299 | 0 | return Err(bp3d_proto::message::Error::Truncated); |
300 | 0 | } |
301 | 0 | item.buffer.unsafe_buffer = self.buffer.unsafe_buffer.index((item_offset as usize)..(item_offset as usize) + size); |
302 | 0 | item_offset += size as isize; |
303 | | } |
304 | 12 | } |
305 | 12 | self.children = children; |
306 | 12 | self.items = items; |
307 | 13 | } |
308 | 25 | let mut offset = self.location.size as isize; |
309 | 46 | for child21 in &mut self.children { |
310 | 21 | if child.location.offset != -1 { Branch (310:16): [True: 1, False: 0]
Branch (310:16): [True: 0, False: 20]
|
311 | 1 | offset = child.location.offset; |
312 | 20 | } |
313 | 21 | if offset as usize >= self.buffer.len() { Branch (313:16): [True: 0, False: 1]
Branch (313:16): [True: 0, False: 20]
|
314 | 0 | return Err(bp3d_proto::message::Error::Truncated); |
315 | 21 | } |
316 | 21 | unsafe { child.buffer.unsafe_buffer.delete() }; |
317 | 21 | child.buffer.unsafe_buffer = self.buffer.unsafe_buffer.index((offset as usize)..); |
318 | | // Again type inference is broken. |
319 | 21 | child.buffer.offset = self.buffer.offset + offset as usize; |
320 | 21 | let size = child.read()?0 ; |
321 | 21 | if (offset as usize) + size > self.buffer.len() { Branch (321:16): [True: 0, False: 1]
Branch (321:16): [True: 0, False: 20]
|
322 | 0 | return Err(bp3d_proto::message::Error::Truncated); |
323 | 21 | } |
324 | 21 | child.buffer.unsafe_buffer = self.buffer.unsafe_buffer.index((offset as usize)..(offset as usize) + size); |
325 | 21 | trace!({name=&*child.path_component.name} {offset=child.buffer.offset}, "size: {}", size); |
326 | 21 | offset += size as isize; |
327 | | } |
328 | 25 | self.buffer.unsafe_buffer = self.buffer.unsafe_buffer.index(..offset as _); |
329 | 25 | Ok(offset as _) |
330 | 41 | } |
331 | | |
332 | 27 | pub fn shape(&mut self) -> bp3d_proto::message::Result<()> { |
333 | 27 | if let Some(component12 ) = self.component.take() { Branch (333:16): [True: 0, False: 2]
Branch (333:16): [True: 12, False: 13]
|
334 | 12 | let items = self.items.take().unwrap_or_else(Vec::new); |
335 | 12 | match component.shape(self, &items) { |
336 | 0 | Err(e) => { |
337 | 0 | self.component = Some(component); |
338 | 0 | return Err(e); |
339 | | } |
340 | 12 | _ => () |
341 | | } |
342 | 12 | self.component = Some(component); |
343 | 12 | self.items = Some(items); |
344 | 15 | } else if self.buffer.is_empty() && self.location.size > 06 { Branch (344:19): [True: 2, False: 0]
Branch (344:45): [True: 1, False: 1]
Branch (344:19): [True: 4, False: 9]
Branch (344:45): [True: 2, False: 2]
|
345 | 3 | trace!({size=self.location.size}, "allocate empty buffer"); |
346 | 3 | self.buffer.unsafe_buffer = UnsafeBuffer::with_capacity(self.location.size); |
347 | 12 | } |
348 | 27 | if !self.location.fixed { Branch (348:12): [True: 1, False: 1]
Branch (348:12): [True: 24, False: 1]
|
349 | 46 | for child21 in &mut self.children { |
350 | 21 | child.shape()?0 |
351 | | } |
352 | 2 | } |
353 | 27 | trace!("buffer after shape: {:?}", self.buffer.as_bytes()); |
354 | 27 | if unsafe { &*self.path_component.parent.get() } .is_none() { Branch (354:12): [True: 1, False: 1]
Branch (354:12): [True: 5, False: 20]
|
355 | 6 | self.flatten()?0 ; |
356 | 21 | } |
357 | 27 | Ok(()) |
358 | 27 | } |
359 | | |
360 | 31 | fn flatten_internal(&mut self) { |
361 | 31 | if self.children.len() > 0 { Branch (361:12): [True: 2, False: 2]
Branch (361:12): [True: 9, False: 18]
|
362 | 11 | let mut v = Vec::with_capacity(self.buffer.len()); |
363 | 11 | let mut offset: usize = 0; |
364 | 36 | for child25 in &mut self.children { |
365 | 25 | if child.location.offset != -1 && child.location.offset7 > offset as _ { Branch (365:20): [True: 3, False: 0]
Branch (365:51): [True: 0, False: 3]
Branch (365:20): [True: 4, False: 18]
Branch (365:51): [True: 3, False: 1]
|
366 | 3 | // The compiler should be able to infer the type isize/usize but as always |
367 | 3 | // type-inference is broken. |
368 | 3 | let len = child.location.offset - offset as isize; |
369 | 3 | offset += v.write(&self.buffer.as_bytes()[..len as usize]).unwrap_or(0); |
370 | 3 | offset += child.location.offset as usize; |
371 | 22 | } |
372 | 25 | child.flatten_internal(); |
373 | 25 | trace!({name=&*child.path_component.name}, "child buffer: {:?}", child.buffer.as_bytes()); |
374 | 25 | offset += v.write(child.buffer.as_bytes()).unwrap_or(0); |
375 | | } |
376 | 11 | trace!({name=&*self.path_component.name}, "master buffer: {:?}", v); |
377 | 11 | unsafe { self.buffer.unsafe_buffer.copy(v.as_slice()) }; |
378 | 20 | } |
379 | 31 | } |
380 | | |
381 | 6 | fn flatten(&mut self) -> bp3d_proto::message::Result<()> { |
382 | 6 | if self.buffer.flat.get() { Branch (382:12): [True: 0, False: 1]
Branch (382:12): [True: 0, False: 5]
|
383 | | // Nothing to do view is already flat! |
384 | 0 | return Ok(()) |
385 | 6 | } |
386 | 6 | self.flatten_internal(); |
387 | 6 | self.read()?0 ; |
388 | 6 | self.buffer.flat.set(true); |
389 | 6 | Ok(()) |
390 | 6 | } |
391 | | |
392 | 0 | pub fn name(&self) -> &str { |
393 | 0 | &self.path_component.name |
394 | 0 | } |
395 | | |
396 | 98 | pub fn get_path(&self) -> String { |
397 | 98 | let mut v = Vec::new(); |
398 | 98 | let mut comp = &self.path_component; |
399 | 98 | v.push(comp.name.clone()); |
400 | 244 | while let Some(parent146 ) = unsafe { &*comp.parent.get() } { Branch (400:19): [True: 14, False: 8]
Branch (400:19): [True: 132, False: 90]
|
401 | 146 | comp = parent; |
402 | 146 | let index = comp.index.get(); |
403 | 146 | if index != -1 { Branch (403:16): [True: 0, False: 14]
Branch (403:16): [True: 0, False: 132]
|
404 | 0 | v.push(format!("[{}].", index) + &comp.name); |
405 | 146 | } else { |
406 | 146 | v.push(comp.name.clone()); |
407 | 146 | } |
408 | | } |
409 | 98 | v.reverse(); |
410 | 98 | v.join(".") |
411 | 98 | } |
412 | | } |
413 | | |
414 | | impl<'a, 'b> Index<&'a str> for BufferView<'b> { |
415 | | type Output = BufferView<'b>; |
416 | | |
417 | 17 | fn index(&self, index: &'a str) -> &Self::Output { |
418 | 17 | match self.get(index) { |
419 | 17 | Some(view) => view, |
420 | 0 | None => panic!("Unable to find view with path '{}'", index) |
421 | | } |
422 | 17 | } |
423 | | } |
424 | | |
425 | | impl<'a, 'b> IndexMut<&'a str> for BufferView<'b> { |
426 | 16 | fn index_mut(&mut self, index: &'a str) -> &mut Self::Output { |
427 | 16 | match self.get_mut(index) { |
428 | 16 | Some(view) => view, |
429 | 0 | None => panic!("Unable to find view with path '{}'", index) |
430 | | } |
431 | 16 | } |
432 | | } |
433 | | |
434 | | impl Drop for BufferView<'_> { |
435 | 33 | fn drop(&mut self) { |
436 | 33 | unsafe { self.buffer.unsafe_buffer.delete() }; |
437 | 33 | } |
438 | | } |